#include <iostream>
using namespace std;

class Person
{
public:
	Person(const char* name = "peter")
		: _name(name)
	{
		cout << "Person()" << endl;
	}

	Person(const Person& p)
		: _name(p._name)
	{
		cout << "Person(const Person& p)" << endl;
	}

	Person& operator=(const Person & p)
	{
		cout << "Person operator=(const Person& p)" << endl;
		if (this != &p)
			_name = p._name;

		return *this;
	}

	~Person()
	{
		cout << "~Person()" << endl;
	}

protected:
	string _name; // 姓名
};


//class Student : public Person
//{
//public:
//	Student(const char* name, int num)
//		: Person(name)
//		, _num(num)
//	{
//		cout << "Student()" << endl;
//	}
//
//	Student(const Student& s)
//		: Person(s)
//		, _num(s._num)
//	{
//		cout << "Student(const Student& s)" << endl;
//	}
//
//	Student& operator = (const Student& s)
//	{
//		cout << "Student& operator= (const Student& s)" << endl;
//		if (this != &s)
//		{
//			Person::operator =(s);
//			_num = s._num;
//		}
//		return *this;
//	}
//
//	~Student()
//	{
//		cout << "~Student()" << endl;
//	}
//
//protected:
//	int _num; //学号
//};

//void Test1()
//{
//	Student s1("jack", 18);
//	Student s2(s1);
//	Student s3("rose", 17);
//	s1 = s3;
//}

class Student : public Person
{
public:
	//构造时先父后子,在初始化列表里顺序是按声明顺序，因此就算把Person(name)写在后面，也会先调用这个
	Student(const char* name = "", int x = 0, const char* address = "")
		//:_name(name) //规定了不能直接碰父类成员
		//: Person(name)
		//父类构造显示调用，可以保证先父后子
		:_x(x)
		,_address(address)
		,_name(Person::_name+'x')
		,Person(name)
	{}

	Student(const Student& st)
		:Person(st)   //调用父类的拷贝构造
		,_x(st._x)
		,_address(st._address)
	{}


	Student& operator=(const Student &st)
	{
		if (this != &st)
		{
			//operator = (st); //错误
			Person::operator= (st);//指定
			_x = st._x;
			_address = st._address;
		}
		return *this;
	}

	//显示写析构
	// 由于多态，析构函数的名字会被统一处理为destructor()
	~Student()// 析构时先子后父
	{
		//父类析构不能显示调用，因为显示调用不能保证先子后父
		// 析构函数会构成隐藏，因此要统一处理
		//Person::~Person();
		cout << "~Student()" << endl;
	}


protected :
	int _x = 1;
	string _address = "湖南";
	string _name;
	//int* _ptr = new int[10]; //此时需要深拷贝
};

//子类默认生成的构造
// 父类成员（整体） -- 默认构造
// 子类自己的内置成员 --一遍不处理
// 子类自己的自定义成员 -- 默认构造

//子类默认生成的拷贝构造   赋值重载和拷贝构造类似
// 父类成员（整体） -- 调用父类的构造
// 子类自己的内置成员 --一 值拷贝
// 子类自己的自定义成员 -- 调用它的拷贝构造
//一遍就不需要自己写，当子类成员涉及深拷贝时，则必须自己实现

//子类默认生成的析构函数
// 父类成员（整体） -- 调用父类的析构
// 子类自己的内置成员 --一 不处理
// 子类自己的自定义成员 -- 调用析构



//子类中，父类那部分成员当成一个整体，调用父类对象函数，复用
void Test2()
{
	Student s1; //只能调默认构造，不写编译器默认生成的属于默认构造，注意父亲的name要初值
	Student s2("张三", 18, "长沙");

	//Student2 s3 = s2; //拷贝构造

	//s1 = s3;

}



int main()
{
	//Test1();
	Test2();

	return 0;
}